/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.sensor.greenseeker;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.EnumMap;
import nl.cloudfarming.client.model.SensorDataFile;
import org.openide.util.NbBundle;

/**
 *
 * @author Gerben Feenstra
 */
public class GreenseekerFileProcessorBorne extends GreenseekerFileProcessor {

    public GreenseekerFileProcessorBorne(File fileToProcess) {
        super(fileToProcess);
    }
        
    // Constant int values
    private static final int HEADER_LENGTH = 672; // 481 = Header length Borne
    private static final int RECORD_LENGTH = 301;
    private final String LOGKEY_TYPE_DISPLAYNAME = NbBundle.getMessage(this.getClass(), "message.info.type.displayname.greenseekerborne");

    
    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HHmmss.SS");
        
        /**
     * Parses one record of a v/d Borne Greenseeker sensorfile.
     *
     * @param payload The record to be processed.
     * @param dataFile The SensorDataFile belonging to this sensor file.
     * @return A record represented as a Greenseeker sensordata object
     * @throws ParseException Exception occurs when date/time cannot be parsed.
     */
    @Override
    protected GreenseekerSensorData parse(String payload, SensorDataFile dataFile) throws GreenseekerParseException {
        // Split payload into fields-array
        String[] fields = getFields(payload);

        EnumMap map = new EnumMap<GreenseekerFileDescriptionBorne, Object>(GreenseekerFileDescriptionBorne.class);
        try{
            for (GreenseekerFileDescriptionBorne greenseekerBorneField : GreenseekerFileDescriptionBorne.values()) {
                if (greenseekerBorneField.isMandatory()) {
                    if (greenseekerBorneField.getTheClass().equals(java.lang.Double.class)) {
                        double theDouble = Double.parseDouble(fields[greenseekerBorneField.getPosition()]);
                        map.put(greenseekerBorneField, theDouble);
                    } else if (greenseekerBorneField.getTheClass().equals(java.lang.Integer.class)) {
                        int theInt = Integer.parseInt(fields[greenseekerBorneField.getPosition()]);
                        map.put(greenseekerBorneField, theInt);
                    } else if (greenseekerBorneField.getTheClass().equals(java.util.Date.class)) {
                        Date theDate = TIME_FORMAT.parse(fields[greenseekerBorneField.getPosition()]);
                        map.put(greenseekerBorneField, theDate);
                    } else {
                        map.put(greenseekerBorneField, fields[greenseekerBorneField.getPosition()]);
                    }
                }
            }
        }
        catch(ParseException e){
            throw new GreenseekerParseException("Error parsing date ", e);
        }
        catch(Exception e){
            throw new GreenseekerParseException(e);
        }

        GreenseekerSensorData sensorData = new GreenseekerSensorData(
                (SensorDataFile) dataFile,
                (Double) map.get(GreenseekerFileDescriptionBorne.OBJECTID),
                (Double) map.get(GreenseekerFileDescriptionBorne.LONGITUDE),
                (Double) map.get(GreenseekerFileDescriptionBorne.LATITUDE),
                (Double) map.get(GreenseekerFileDescriptionBorne.SPEED),
                (Double) map.get(GreenseekerFileDescriptionBorne.HEADING),
                (Double) map.get(GreenseekerFileDescriptionBorne.ELEVATION),
                (Double) map.get(GreenseekerFileDescriptionBorne.NDVI),
                (Double) map.get(GreenseekerFileDescriptionBorne.VI2ND),
                (Double) map.get(GreenseekerFileDescriptionBorne.RED54),
                (Double) map.get(GreenseekerFileDescriptionBorne.NIR54),
                (Double) map.get(GreenseekerFileDescriptionBorne.RED55),
                (Double) map.get(GreenseekerFileDescriptionBorne.NIR55),
                (Double) map.get(GreenseekerFileDescriptionBorne.RED57),
                (Double) map.get(GreenseekerFileDescriptionBorne.NIR57),
                (Double) map.get(GreenseekerFileDescriptionBorne.RED53),
                (Double) map.get(GreenseekerFileDescriptionBorne.NIR53),
                (Double) map.get(GreenseekerFileDescriptionBorne.RED56),
                (Double) map.get(GreenseekerFileDescriptionBorne.NIR56),
                (Double) map.get(GreenseekerFileDescriptionBorne.RED58),
                (Double) map.get(GreenseekerFileDescriptionBorne.NIR58));
        return sensorData;
    }

    @Override
    protected int getHeaderLength() {
        return HEADER_LENGTH;
    }

    @Override
    protected int getRecordLength() {
        return RECORD_LENGTH;
    }

    /**
     * Concrete subclasses must override this method to return the displayname of that sensorprocessor to be displayed in the log.
     * For example: "ASC-340 Cropcircle"
     * 
     * Primary use is for logging, for example: [Info] Start processing of ASC-340 Cropcircle sensor file 010710AD.CSV
     * 
     * @return 
     */
    @Override
    protected String getLogDisplayName() {
        return LOGKEY_TYPE_DISPLAYNAME;
    }
}
